/**
 * 游戏循环管理器
 * 负责管理游戏的主循环，包括更新和渲染
 * @class
 */

export interface GameLoopCallbacks {
  /** 更新回调函数 */
  update: (deltaTime: number) => void
  /** 渲染回调函数 */
  render: (deltaTime: number) => void
}

/**
 * 游戏循环类
 */
export class GameLoop {
  private isRunning: boolean = false
  private lastTime: number = 0
  private animationFrameId: number | null = null
  private callbacks: GameLoopCallbacks
  private targetFPS: number = 60
  private frameInterval: number = 1000 / 60 // 16.67ms for 60fps
  private accumulator: number = 0

  /**
   * 创建游戏循环实例
   * @param callbacks - 游戏循环回调函数
   * @param targetFPS - 目标帧率，默认60fps
   */
  constructor(callbacks: GameLoopCallbacks, targetFPS: number = 60) {
    this.callbacks = callbacks
    this.targetFPS = targetFPS
    this.frameInterval = 1000 / targetFPS
  }

  /**
   * 开始游戏循环
   */
  start(): void {
    if (this.isRunning) {
      return
    }

    this.isRunning = true
    this.lastTime = performance.now()
    this.accumulator = 0
    this.loop()
  }

  /**
   * 停止游戏循环
   */
  stop(): void {
    this.isRunning = false
    if (this.animationFrameId !== null) {
      cancelAnimationFrame(this.animationFrameId)
      this.animationFrameId = null
    }
  }

  /**
   * 暂停游戏循环
   */
  pause(): void {
    this.isRunning = false
    if (this.animationFrameId !== null) {
      cancelAnimationFrame(this.animationFrameId)
      this.animationFrameId = null
    }
  }

  /**
   * 恢复游戏循环
   */
  resume(): void {
    if (!this.isRunning) {
      this.isRunning = true
      this.lastTime = performance.now()
      this.loop()
    }
  }

  /**
   * 设置目标帧率
   * @param fps - 目标帧率
   */
  setTargetFPS(fps: number): void {
    this.targetFPS = fps
    this.frameInterval = 1000 / fps
  }

  /**
   * 获取当前是否正在运行
   * @returns 是否正在运行
   */
  isActive(): boolean {
    return this.isRunning
  }

  /**
   * 主循环函数
   */
  private loop = (): void => {
    if (!this.isRunning) {
      return
    }

    const currentTime = performance.now()
    const deltaTime = currentTime - this.lastTime
    this.lastTime = currentTime

    // 累积时间，用于固定时间步长更新
    this.accumulator += deltaTime

    // 固定时间步长更新
    while (this.accumulator >= this.frameInterval) {
      try {
        this.callbacks.update(this.frameInterval)
      } catch (error) {
        console.error('游戏更新错误:', error)
      }
      this.accumulator -= this.frameInterval
    }

    // 渲染
    try {
      this.callbacks.render(deltaTime)
    } catch (error) {
      console.error('游戏渲染错误:', error)
    }

    // 请求下一帧
    this.animationFrameId = requestAnimationFrame(this.loop)
  }
}